<?php

namespace adminmatrix\plugin\command;

use Symfony\Component\Process\Exception\LogicException;
use think\console\Command;
use think\console\Input;
use think\console\Output;

class Uninstall extends Command
{
    protected string $pluginName;
    protected string $path;

    protected function configure()
    {
        $this->setName("plugin:uninstall")
            ->addOption("--plugin", "-p", 3, "要卸载的插件名称")
            ->setDescription("插件卸载");
    }

    protected function execute(Input $input, Output $output)
    {
        if (!$input->hasOption("plugin"))
            throw new LogicException("插件名称不能为空 --plugin=插件名 或者 -p 插件名称");

        $pluginName = $this->pluginName = $input->getOption("plugin");
        if (is_null($pluginName))
            throw new LogicException("插件名称不能为空 --plugin=插件名 或者 -p 插件名称");

        $path = $this->path = $this->app->getRootPath() . "plugins/$pluginName";
        if (!file_exists($path))
            throw new LogicException(sprintf("插件 %s 不存在", $pluginName));

        $output->info(sprintf("准备卸载插件 -> %s", $pluginName));

        $this->uninstallDatabase($pluginName, $output);
        $this->uninstallComposer($pluginName, $output);

        $output->info("\n卸载完成！");
    }

    protected function uninstallDatabase($pluginName, Output $output)
    {
        $this->output->writeln("开始卸载数据库");
        $rootPath = $this->app->getRootPath();

        // 1. 获取所有 up 的 migration 版本号
        $cmd = 'php think plugin:migrate_status --app=' . escapeshellarg($pluginName);
        $versions = [];
        $proc = proc_open($cmd, [
            1 => ['pipe', 'w'],
            2 => ['pipe', 'w'],
        ], $pipes, $rootPath);

        if (is_resource($proc)) {
            while (!feof($pipes[1])) {
                $line = fgets($pipes[1]);
                if ($line !== false) {
                    // 匹配 up 状态的 migration 版本号
                    if (preg_match('/up\s+(\d{14})/', $line, $match)) {
                        $versions[] = $match[1];
                    }
                }
            }
            fclose($pipes[1]);
            fclose($pipes[2]);
            proc_close($proc);
        }

        if (empty($versions)) {
            $output->info("无需要回滚的 migration。");
            return;
        }

        // 2. 倒序回滚
        rsort($versions);
        foreach ($versions as $version) {
            $rollbackVersion = substr($version, 0, 13); // 只取前13位
            $cmd = sprintf(
                'php think plugin:migrate_back --app=%s -t %s',
                $pluginName,
                (string) $rollbackVersion
            );
      
            $output->info("回滚 migration 版本: $version");
            $proc = proc_open($cmd, [
                1 => ['pipe', 'w'],
                2 => ['pipe', 'w'],
            ], $pipes, $rootPath);

            if (is_resource($proc)) {
                while (!feof($pipes[1]) || !feof($pipes[2])) {
                    if (!feof($pipes[1])) {
                        $line = fgets($pipes[1]);
                        if ($line !== false) {
                            echo $line;
                            flush();
                        }
                    }
                    if (!feof($pipes[2])) {
                        $line = fgets($pipes[2]);
                        if ($line !== false) {
                            echo $line;
                            flush();
                        }
                    }
                }
                fclose($pipes[1]);
                fclose($pipes[2]);
                proc_close($proc);
            }
        }
        $this->output->writeln("数据库卸载完成");
    }

    protected function uninstallComposer($pluginName, Output $output)
    {
        $this->output->writeln("开始卸载 composer 依赖");
        $pluginComposerFile = $this->app->getRootPath() . "plugins/$pluginName/composer.json";
        if (!file_exists($pluginComposerFile)) {
            $output->info("未检测到 composer.json，无需卸载依赖。");
            return;
        }
        $pluginComposer = json_decode(file_get_contents($pluginComposerFile), true);
        $rootPath = $this->app->getRootPath();

        // 获取其他插件依赖统计
        $otherDeps = $this->getAllPluginComposerDependencies($pluginName);

        foreach ($pluginComposer as $package => $version) {
            // 如果其他插件也依赖该包，则跳过卸载
            if (isset($otherDeps[$package]) && count($otherDeps[$package]) > 0) {
                $output->warning("依赖 $package 也被其他插件使用，跳过卸载。");
                continue;
            }
            $cmd = 'composer remove ' . escapeshellarg(trim($package)) . ' --no-interaction --ansi';
            $output->info("卸载 composer 依赖: $package");
            $proc = proc_open($cmd, [
                1 => ['pipe', 'w'],
                2 => ['pipe', 'w'],
            ], $pipes, $rootPath);

            if (is_resource($proc)) {
                while (!feof($pipes[1]) || !feof($pipes[2])) {
                    if (!feof($pipes[1])) {
                        $line = fgets($pipes[1]);
                        if ($line !== false) {
                            echo $line;
                            flush();
                        }
                    }
                    if (!feof($pipes[2])) {
                        $line = fgets($pipes[2]);
                        if ($line !== false) {
                            echo $line;
                            flush();
                        }
                    }
                }
                fclose($pipes[1]);
                fclose($pipes[2]);
                proc_close($proc);
            }
        }
        $this->output->writeln("composer 依赖卸载完成");
    }

    protected function getAllPluginComposerDependencies($currentPlugin)
    {
        $pluginsDir = $this->app->getRootPath() . 'plugins/';
        $allDeps = [];
        foreach (glob($pluginsDir . '*/composer.json') as $file) {
            $pluginName = basename(dirname($file));
            if ($pluginName === $currentPlugin) {
                continue; // 跳过当前卸载的插件
            }
            $composer = json_decode(file_get_contents($file), true);
            if (is_array($composer)) {
                foreach ($composer as $package => $version) {
                    $allDeps[$package][$pluginName] = true;
                }
            }
        }
        return $allDeps; // 结构: [包名 => [插件名1, 插件名2, ...]]
    }
} 